package cn.lhl01.sys.handler;

import cn.lhl01.common.ApiException;
import cn.lhl01.common.Results;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
import java.util.stream.Collectors;

@RestControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice {

	// 参数格式异常处理
	@ExceptionHandler({IllegalArgumentException.class})
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Results badRequestException(IllegalArgumentException exception) {
		exception.printStackTrace();
		log.error("参数格式不合法：" + exception.getMessage());
		//return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + "", "参数格式不符！");
		return Results.paramError(exception.getMessage());
	}

	// 参数缺失异常处理
	@ExceptionHandler({MissingServletRequestParameterException.class})
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Results badRequestException(MissingServletRequestParameterException exception) {
		exception.printStackTrace();
		//return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + "", "缺少必填参数！");
		return Results.paramError(exception.getMessage());
	}

	// 参数校验异常处理 MethodArgumentNotValidException
	@ExceptionHandler({MethodArgumentNotValidException.class})
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Results badRequestException(MethodArgumentNotValidException exception) {
		exception.printStackTrace();
		return Results.paramError(exception.getBindingResult().getFieldError().getDefaultMessage());
	}

	// 参数校验异常处理 BindException
	@ExceptionHandler({BindException.class})
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Results badRequestException(BindException exception) {
		exception.printStackTrace();
		return Results.paramError(exception.getBindingResult().getFieldError().getDefaultMessage());
	}

	// 参数校验异常处理 ConstraintViolationException
	@ExceptionHandler({ConstraintViolationException.class})
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	public Results badRequestException(ConstraintViolationException exception) {
		exception.printStackTrace();

		Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
		String collect = constraintViolations.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("##"));
		return Results.paramError(collect);
	}


	// 权限不足异常处理
	@ExceptionHandler({AccessDeniedException.class})
	@ResponseStatus(HttpStatus.FORBIDDEN)
	public Results badRequestException(AccessDeniedException exception) {
		exception.printStackTrace();
		//return new ResponseInfo(HttpStatus.FORBIDDEN.value() + "", exception.getMessage());
		return Results.accessDenied();
	}


	// 业务型的异常  这种http的状态按正常出
	@ExceptionHandler(ApiException.class)
	@ResponseStatus(value = HttpStatus.OK)
	public Results handleTypeMismatchException(ApiException ex) {
		ex.printStackTrace();
		log.error("ApiException异常，{}", ex.getMessage());
		return Results.apiError(ex);
	}

	// 空指针异常
	@ExceptionHandler(NullPointerException.class)
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
	public Results handleTypeMismatchException(NullPointerException ex) {
		ex.printStackTrace();
		log.error("空指针异常，{}", ex.getMessage());
		//return new JsonResult("500", "空指针异常");
		return Results.serverError("空指针异常");
	}

	/**
	 * 系统异常处理
	 * 兜底异常
	 *
	 * @param ex
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
	public Results handleUnexpectedServer(Exception ex) {
		ex.printStackTrace();
		log.error("系统异常：", ex);
		//return Results.serverError("500", "系统发生异常，请联系管理员");
		return Results.serverError();
	}

	/**
	 * 系统异常处理
	 * 兜底异常
	 *
	 * @param throwable
	 * @return
	 */
	@ExceptionHandler(Throwable.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Results exception(Throwable throwable) {
		throwable.printStackTrace();
		log.error("系统异常", throwable);
		//return new ResponseInfo(HttpStatus.INTERNAL_SERVER_ERROR.value() + "系统异常，请联系管理员！");
		return Results.serverError();
	}
}


